package com.example.springbootdemo.queue;


import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

class ShareData{

    private int number = 0;

    private Lock lock = new ReentrantLock();

    private Condition condition = lock.newCondition();

    public void add() throws Exception {
        lock.lock();
        try {
            //防止虚假唤醒
            while(number != 0){
                condition.await();
            }
            //干活
            number ++;
            //通知唤醒
            System.out.println(Thread.currentThread().getName() + "\t" + number);
            condition.signalAll();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }

    public void sub() throws Exception {
        lock.lock();
        try {
            //防止虚假唤醒
            while(number == 0){
                condition.await();
            }
            //干活
            number --;
            //通知唤醒
            System.out.println(Thread.currentThread().getName() + "\t" + number);
            condition.signalAll();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }

}

/**
 * @author cici
 *  * 高内聚，低耦合
 *  题目： 一个初始化值为零的变量，两个线程对其交替操作，一个加一，一个减一，来5轮
 *
 *  1、线程   操作  资源类
 *  2、判断   干活   通知
 *  3、 防止虚假唤醒，多线程防止虚假唤醒要用while，防止虚假唤醒的目的可能是线程上下文切换时的浪费
 */
public class ProdConsumerTranditionalDemo {

    public static void main(String[] args) {
        ShareData shareData = new ShareData();

        new Thread(() ->{
            for (int i = 0; i < 5; i++) {
                try {
                    shareData.add();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        },"AA").start();

        new Thread(() ->{
            for (int i = 0; i < 5; i++) {
                try {
                    shareData.sub();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        },"BB").start();
    }
}
